package org.example.iot;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioChannelOption;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

public class Test0x0200 {

    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup worker = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.group(worker);
        bootstrap.option(NioChannelOption.TCP_NODELAY, true);
        bootstrap.handler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel ch) throws Exception {
                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                    //和服务器建立连接之后的回调
                    @Override
                    public void channelActive(ChannelHandlerContext ctx) throws Exception {
                        System.out.println("连接建立");
                        //执行登录
                        byte[] loginBytes = ByteBufUtil.decodeHexDump("028f525c6500990001014457475a434a59323331313038393939322e30322e30303031015b525c6538363531333730363131313638383934363030383435343337303332383338393836303443353130323232303237333238331f3c1f2c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009f130d0a");
                        ctx.writeAndFlush(Unpooled.buffer().writeBytes(loginBytes));
                        TimeUnit.SECONDS.sleep(5);


                        /**
                         * 025034dc5f002b000202010101014457475a434a59323331323138313032010101014457475a434a5932333132313831303376b50d0a
                         */
                        //上报传感器信息
                        //头部
                        byte[] bytes1 = ByteBufUtil.decodeHexDump("025034dc5f");

                        ByteBuf byteBuf= ByteBufAllocator.DEFAULT.buffer();
                        byteBuf.writeBytes(bytes1);
                        //数据长度 = 指令码 + 传感器数量 + 传感器信息
                        byteBuf.writeShort(2+1+(20*1));
                        //写入指令码
                        byteBuf.writeBytes(ByteBufUtil.decodeHexDump("0002"));
                        //写入传感器数量
                        byteBuf.writeByte(1);
                        //写入20字节445747
                        byteBuf.writeBytes(ByteBufUtil.decodeHexDump("04010101"));
                        byteBuf.writeBytes("DWGZCJY261100001".getBytes(StandardCharsets.UTF_8));
                        //写入CRE
                        byte[] crcBytes = crc16CCITTFalse(ByteBufUtil.getBytes(byteBuf));
                        byteBuf.writeBytes(crcBytes);
                        //写入尾部
                        byteBuf.writeBytes(ByteBufUtil.decodeHexDump("0d0a"));
                        ctx.writeAndFlush(byteBuf);

                        /**
                         * 上传数据包
                         */
                        byte[] bytes = ByteBufUtil.decodeHexDump("02E45BD46502E1020001755BD46500007A4204002E002E00C21F59BC0A3E3C3CC2177E3F932955BCAC51343C67077E3F8C7A52BC3A19413C83F57D3FF8D651BCE3C9493C120F7E3F83E64EBCBE67493CAC2A7E3F980549BC86DD413C6D1F7E3FB5D345BCAB3F423C39FF7D3F2CA949BC44AD443CD31A7E3F201E53BCE9A53D3CF6207E3FE88159BCCCD7403CEA077E3FF8C45FBCD386433C8F0E7E3FFAA960BCD66B443CEB1E7E3F660660BC6A0F453C060D7E3F51F957BC6CF4453CA4FB7D3F6DC754BC672A443CA6297E3F3DEC4FBC3DFE413CFC387E3F15A54EBCA0C63D3C7D0B7E3F0B114BBC364F3F3CC7017E3F520B4ABC5E96403C01237E3FCEAA4FBC672A443C4C307E3F220354BC672A443C880D7E3F2C9757BCF41E423CD91B7E3F29B256BCB009443C6D367E3F27CD55BC3DFE413C61067E3F220354BC7E2E3F3C060D7E3FB6A654BC5BB13F3C84237E3F41B651BCD1A1423C8F0E7E3FF5F150BC607B413C67077E3F1B5451BC10ED3E3CFB217E3F458053BCD386433CD31A7E3FBB7056BCB7B8463C33157E3F9DBD58BC9256463CD31A7E3F32465ABCF41E423CF01F7E3FE3B757BCCCD7403C880D7E3F1A6F50BCED6F3F3C28137E3FED5D4DBC787F3C3C89247E3F1B5451BCED6F3F3C950F7E3FB4C153BCCEBC413CD8047E3FB6A654BC8D8C443C89247E3FBB7056BC8F71453CCE197E3FDEED55BC88C2423CBD167E3F70AC55BCD1A1423C611D7E3F932955BC3DFE413C73207E3F4A4A55BC12D23F3C17107E3FAB2D50BCC70D3F3C45187E3F624E50BCA4903F3CDE1C7E3F178A4FBC2130453CF7377E3F624E50BC6545433C0C257E3F6BE253BCED6F3F3C61067E3FF8D651BC7E2E3F3C17107E3F201E53BC3DFE413C5C1C7E3FBD5557BCCEBC413C830C7E3F091A58BCCCD7403CCE197E3F914454BC8113403CFB217E3FD18F50BC57E73D3CDE1C7E3F1A6F50BCEA8A3E3CF01F7E3FEF424EBC5BB13F3CFB217E3F624E50BC12D23F3C060D7E3FD92354BC8D8C443C96267E3F729156BC6545433C45187E3FF25F0D0A");
                        ByteBuf buffer = Unpooled.buffer();
                        buffer.writeBytes(bytes);
                        ctx.writeAndFlush(buffer);

                        /**
                         * 百包校验
                         */
                        byte[] bytes2222 = ByteBufUtil.decodeHexDump("024196486500020401BDED0D0A");
                        ByteBuf buffer222 = Unpooled.buffer();
                        buffer.writeBytes(bytes2222);
                        ctx.writeAndFlush(buffer222);

                    }
                });
            }
        });
        ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8380).sync();
        Channel channel = channelFuture.channel();

    }

    public static byte[] crc16CCITTFalse(byte[] bytes) {
        int crc = 0xffff; // initial value
        int polynomial = 0x1021; // poly value
        for (int index = 0; index < bytes.length; index++) {
            byte b = bytes[index];
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b >> (7 - i) & 1) == 1);
                boolean c15 = ((crc >> 15 & 1) == 1);
                crc <<= 1;
                if (c15 ^ bit){
                    crc ^= polynomial;
                }
            }
        }
        crc &= 0xffff;
        return new byte[] { (byte) ((0xff00 & crc) >> 8),(byte) (0xff & crc)  };
    }
}
